import java.util.ArrayList;

import java.util.List;
/**
 * @author Grupo5 Aula2 LLP
 *			Renato Vieira <renatovieira@hotmail.com>
 * 			Carlos Valverde <carlosvalverdegomes@gmail.com> 
 * 			Adonai Diófanes <adonaibm@gmail.com>
 *			Emerson Vasconcelos Costa <emersonvasconceloscosta@gmail.com> 
 *			Leonardo Silveira <lasouzabr@gmail.com>
 */

public class Pessoa {
	
	private String nome;
	private int idade;
	private char sexo;
	private Pessoa conjuge;
	private Pessoa pai;
	private Pessoa mae;
	private String retorno;
	
	private List<Pessoa> divorcio = new ArrayList<Pessoa>();
	private List<Pessoa> casamento = new ArrayList<Pessoa>();
	

	public static int n_pessoas;
	private static List<Pessoa> todas = new ArrayList<Pessoa>();
	
	/**
	 * Construtores: Caso o objeto seja instanciado sem nenhum argumento,
	 *  por padrao adiciona-se um nome e a idade = 0
	 * @param String pNome @param int pIdade @param char pSexo
	 * @return void
	 */
	
	public Pessoa(){
		// TODO > {Ideia} Uma ideia aqui È n„o obrigar a setar o sexo, todo sexo inicia-se como Masculino
		// 		  se o obj for instanciado como Mulher, na classe Mulher agente faz setSexo('F');
		nome = "Sem IdentificaÁ„o";
		idade = 0;
		// @Atencao: Ao criar uma nvoa pessoa, automaticamente essa pessoa È adicionada a uma lista de pessoas
		// Essa lista de pessoa È uma vari·vel est·tica (Nome: todas)
		todas.add(this);
		++n_pessoas;
	}
	
	// Esse consrutor trabalha com argumentos, o programador deve passar o nome idade e sexo do objeto Pessoa
	public Pessoa( String pNome, int pIdade, char pSexo){
		this();
		nome  = pNome;
		idade = pIdade;
		sexo  = pSexo;
		
	}
	
	
	
	
	
	/* ***************************************************
	 * METODOS
	 * **************************************************/ 
	
	// [PAI] Verificar Paternidade
	private String verificarPai( Pessoa p ){
		retorno = null;
		if(p.pai!=null && this == p.pai){
			retorno = this.nome + " È pai de " + p.nome;
		} else if(this.pai != null && p == this.pai){
			// TODO: Verificar se È filho ou filha (mulher ou homem) de acordo com o sexo do obj {"sexo do obj foi foda em"}
			retorno = this.nome + " È filho(a) " + p.nome;
		}
		
		return retorno;
	}
	
	// [MAE] Verificar Mae
	private String verificarMae( Pessoa p ){
		retorno = null;
		if( this.mae != null && this.mae == p ){
			retorno = this.nome + " È filho(a) de " + p.nome;
		} else if( p.mae != null && p.mae == this){
			retorno = this.nome + " È m„e de " + p.nome;
		}
		return retorno;
	}
	
	// [AVOS E NETOS] Verificar avos e netos
	private String verificarAvoNeto( Pessoa p ){
		retorno = null;
		// Verificacao de paretescos entre avos e netos por parte de pai
		if( (this.pai != null) && ( this.pai.pai != null ) && (this.pai.pai == p) ){
			retorno = this.nome + " È neto(a) de " + p.nome;
		}
		else if( (this.pai != null) && ( this.pai.mae != null ) && (this.pai.mae == p) ){
			retorno = this.nome + " È neto(a) de " + p.nome;
		}
		else if ( ( (p.pai != null) && (p.pai.pai != null) && (p.pai.pai == this) ) ){
			retorno = this.nome + " È avÙ de " + p.nome;
		}
		else if ( ( (p.pai != null) && (p.pai.mae != null) && (p.pai.mae == this) ) ){
			retorno = this.nome + " È avÛ de " + p.nome;
		}
		else if( (this.mae != null) && ( this.mae.pai != null ) && (this.mae.pai == p) ){
			retorno = this.nome + " È neto(a) de " + p.nome;
		}
		else if( (this.mae != null) && ( this.mae.mae != null ) && (this.mae.mae == p) ){
			retorno = this.nome + " È neto(a) de " + p.nome;
		}
		else if ( ( (p.mae != null) && (p.mae.pai != null) && (p.mae.pai == this) ) ){
			retorno = this.nome + " È avÙ de " + p.nome;
		}
		else if ( ( (p.mae != null) && (p.mae.mae != null) && (p.mae.mae == this) ) ){
			retorno = this.nome + " È avÛ de " + p.nome;
		}
		return retorno;
	}
	
	// [TIO] Verificar Tio
	private String verificarTio( Pessoa p ){
		retorno = null;
		if ( (this.pai != null) && (p.pai != null) && ( (this.pai == p.pai.pai) || (this.pai == p.mae.pai) ) ){
			// TODO: Verificar se È tio ou tia de acordo com o sexo do obj
			retorno = this.nome + " È tio(a) de " + p.nome;
		}
		return retorno;
	}

	// [SOBRINHO]
	private String verificarSobrinho( Pessoa p ){
		retorno = null;
		if( (this.pai != null) && ( this.pai.pai != null) && (p.pai != null) && (this.pai.pai == p.pai) ){
			retorno = this.nome + " È sobriho(a) de " + p.nome;
		} else if( (this.mae != null) && (this.mae.mae != null) && (p.mae != null) && (this.mae.mae == p.mae) ){
			retorno = this.nome + " È sobriho(a) de " + p.nome;
		}
		return retorno;
	}
	
	// [ IRMAOS ]
	private String verificarIrmaos( Pessoa p){
		retorno = null;
		if( ( this.pai != null && p.pai != null && this.pai == p.pai ) ||
			( this.mae !=null && p.mae != null && this.mae == p.mae ) ){
				retorno = this.nome + " È irm„o " + "de " + p.nome;
		}
		return retorno;
	}
	
	// TODO: Fazer o metodo de verificar se s„o primos
	public void verificarPrimos(Pessoa p){
		// Digite o cÛdigo aqui dentro
	}
	
	
	/*
	 * Metodo de verificar parentesco
	 * Esse mÈtodo verifica o parentesco e j· d· a saÌda de qual È o grau de parentesco que a pessoa tem com o objeto
	 * 
	 * */
	public void verificarParentesco( Pessoa p ){
		
		// CONJUGES
		if( (this.conjuge == p) || (p.conjuge == this) ){
			// TODO: Verificar se È esposa ou marido de acordo com o sexo do obj
			System.out.println( this.nome + " È conjuge de " + p.nome);
		}
		
		// Verificar Paternidade
		else if( verificarPai(p) != null ){
			System.out.println( verificarPai(p) );
		}
		
		// Verificar Maternidade
		else if( verificarMae(p) != null ){
			System.out.println( verificarMae(p) + "!");
		}
		
		else if( verificarAvoNeto(p) != null){
			System.out.println( verificarAvoNeto(p) + "!" );
		}

		// Tio
		else if ( verificarTio(p) != null ){
			System.out.println( verificarTio(p) + "!" );
		}
		
		// Sobrinho
		else if( verificarSobrinho(p) != null ){
			System.out.println( verificarSobrinho(p) + "!" );
		}
					
		// Irmao
		else if( verificarIrmaos(p) != null ){
			System.out.println( verificarIrmaos(p) + "!" );
		}
		
		// A propria pessoa
		else if( this.equals(p) || (p.equals(this)) ){
			System.out.println(this.nome + " e " + p.nome + " s„o a mesma pessoa!");
		} 
		
		else {
			System.out.println(this.nome + " e " + p.getNome() + " n„o s„o parentes.");
		}
	}
	

	/**
	 * METODO: Verificar Parentesco
	 * Esse mÈtodo foi desenvolvido apenas para ser utilizado pelo metodo CASAR
	 *  retorno 		 = 0 pessoa apta a casar
	 * retorno 		 = 1 n„o pode casar porque È parente
	 * retorno = 2 casamento entre primos vai ser permitido (de acordo com o @valverde rs...) (falta fazer) 
	 * @param Pessoa p
	 * @return int
	 */
	private int verificarParentescoCasar( Pessoa p ){
		
		int retorno = 0;
		
		// TODO: PERMITIR CASAMENTO DE PRIMOS (verifique a linha 137)
		
		// CONJUGES
		if( (this.conjuge == p) || (p.conjuge == this) ){ retorno = 1; }
		
		// Verificar Paternidade
		else if( verificarPai(p) != null ){ retorno = 1; }
		else if( verificarAvoNeto(p) != null){ retorno = 1;	}

		// Tio
		else if ( verificarTio(p) != null ){ retorno = 1; }
		
		// Sobrinho
		else if( verificarSobrinho(p) != null ){ retorno = 1; }
					
		// Verificar Maternidade
		else if( verificarMae(p) != null ){ retorno = 1; }
		
		// Irmao
		else if( verificarIrmaos(p) != null ){ retorno = 1; }
		
		// A propria pessoa
		else if( this.equals(p) || (p.equals(this)) ){ retorno = 1; } 

		return retorno;
	}
	
	/**
	 * realiza casamento entre duas pessoas 
	 * @param Pessoa p
	 * @return void
	 */
	public void casar(Pessoa p){
		System.out.println("----- CASAMENTO -----");
		// verificacoes
			// Verificar se a pessoa ou o objeto ja È casado
			if ( this.conjuge != null ) {
				System.out.println(this.nome + " ja e casado(a)!");
			} else if (p.conjuge != null) {
				System.out.println( p.nome + " ja e casado(a)!" );
			}
			// Verificar se eh menor de idade
			else if( (p.idade < 18) || (this.idade < 18) ){
				//  TODO > Implementar o mÈtodo adicional Metodo adicional [CalculaIdadeCasamento]
				// 		   Esse metodo j· esta pronto na classe Pessoa
				System.out.println(p.nome + " ou " + this.nome + " È menor de idade e n„o casa!");
			} 
			
			// Verificar se j· s„o parentes
			// TODO > Permitir casamento entre primos 
			else if( verificarParentescoCasar(p) == 1 ){
				System.out.println( this.nome + " n„o pode casar-se com " + p.nome + " pois s„o parentes!" );
			}
			
			// Verificar se o objeto È igual a pessoa
			else if( this.nome.equals(p) ){
				System.out.println("Nao pode casar consigo mesmo!");
			}
			else {
				this.setConjuge( p );
				p.setConjuge( this );
				casamento.add(p);
				p.casamento.add(this);
				
				System.out.println(this.nome + " e casou-se com " + this.conjuge.nome );
				//System.out.println(p.nome + " e casou-se com " + p.conjuge.nome);
			}
	}
	
	/*
	 * METODO: VerificaÁ„o de Estado Civil
	 * 
	 * */
	public void verificarEstadoCivil(){
		if(this.conjuge == null && this.divorcio.isEmpty()){
			System.out.println("Solteiro");
		} else if(this.conjuge == null && !this.divorcio.isEmpty()){
			System.out.println("Divorciado");
		} else if (this.conjuge != null) {
			System.out.println("Casado");
		} else {
			System.out.println("NADA");
		}
	}
	
	/*
	 * METODO: Gerar Filhos
	 * TODO: Verificar se nesse metodo tem como passar o nome do pai, nome da mae, e novo objeto filho 
	 * (ex: Pessoa p = gerarFilhos( "Quico", 15, 'M', QuicoPai, MaeDeQuico ) , public Pessoa gerarFilhos(...)
	 * */
	public void gerarFilhos(Pessoa p){
		if ((this.conjuge == null)) {
			System.out.println(this.nome + " n„o È casado, n„o pode ter filhos");
		}
		else
		{
			if (sexo == 'M') {
				p.pai = this;
			}
			else
			{
				p.mae = this;
			}
		}
	}
	
	/*
	 * METODO: Divorcio
	 * */
	public void divorciar(){
		
			System.out.println("----- Divorcio -----");
		
			// Verificar se a pessoa tem conjuge e se o conjuge dessa pessoa È o obj atual
			if( this.getConjuge() != null && this.getConjuge().getConjuge().equals(this) ){
		
				// Resgatar a pessoa que ele esta casado
				Pessoa D = this.getConjuge();
				
				// Divorciar a pessoa em questao
			    this.divorcio.add(D);
			    this.conjuge = null;
			    
			    // Divorciar o conjuge
			    D.divorcio.add(this);
			    D.conjuge = null;
			    
			    // Imprimir mensagem de divorcio com sucesso
			    System.out.println(this.getNome() + " divorciou-se de " + D.getNome());
			    
			} else {
				System.out.println(this.nome + " n„o È casado(a)!");
			}
	}
	
	/*
	 * METODO: Listar Filhos
	 * */
	public void listarFilhos(){
		
		int contaFilho = 0;
		Pessoa temp;
				
		// Percorrer todas as entradas de pessoas e verificar se == pai || mae
		for (int i = 0; i < Pessoa.n_pessoas; i++) {
			if((todas.get(i).getPai()==null)||(todas.get(i).getMae()==null))
				continue;
			temp=((this.sexo == 'M')?todas.get(i).getPai():todas.get(i).getMae());
			
			if (this.equals(temp)){
				++contaFilho;
				System.out.println("Eu "+ this.getNome()+ ((this.sexo == 'M')?" sou Pai de ":" sou Mae de ")+todas.get(i).getNome());
			}
				
			}
		
		
		// Verificar se o objeto possui filhos
		if( contaFilho == 0 ){
		System.out.println( this.getNome() + " n„o tem filhos!" ); 
		}else System.out.println("Eu tenho "+contaFilho +" Filhos");
		
		
		
	}
	
	/*
	 * METODO: Calcular Idade (esse foi o mÈtodo escolhido para a "nova funcionalidade a sua escolha"
	 * "TambÈm ser· necess·rio, alÈm das funcionalidades j· citadas, implementar no sistema
	 * uma nova funcionalidade a sua escolha e adicionalmente, criar um mÈtodo
	 * est·tico. Seja criativo!"
	
	public int CalculaIdadeCasamento(int idade){
	       int idadeCasa = idade;
	           if (idade < 18) {
	              idadeCasa = 18 - idade;
		        }        
	              return idadeCasa;              
	}	
	 * */
	// TODO: ListarCasamentos

	public void listarCasamentos(){
		
		
		for(int i=0; i<casamento.size(); i++){
			
			System.out.println( i + " : " + casamento.get(i).getNome() );
		}
		
	}


	
	public String getNome() {
		return nome;
	}
	public void setNome(String nome) {
		this.nome = nome;
	}
	public int getIdade() {
		return idade;
	}
	public void setIdade(int idade) {
		this.idade = idade;
	}
	public char getSexo() {
		return sexo;
	}
	public void setSexo(char sexo) {
		this.sexo = sexo;
	}
	public Pessoa getConjuge() {
		return conjuge;
	}
	public void setConjuge(Pessoa conjuge) {
		this.conjuge = conjuge;
	}
	public List<Pessoa> getDivorcio() {
		return divorcio;
	}
	public void setDivorcio(List<Pessoa> divorcio) {
		this.divorcio = divorcio;
	}
	public Pessoa getPai() {
		return pai;
	}
	public void setPai(Pessoa pai) {
		this.pai = pai;
	}
	public Pessoa getMae() {
		return mae;
	}
	public void setMae(Pessoa mae) {
		this.mae = mae;
	}	
	

	
}